<?php


namespace App\Services\Repo;

use App\Models\Company;
use App\Models\Project;
use App\Models\SimCard;
use App\Models\WxClient;
use App\Services\HelpService;
use App\Plugins\Wechat\Client;
use App\Services\Excel\ExcelReader;
use Helper;
use Excel;
use DB;
use App\Services\Excel\ImportError;
use App\Services\Interfaces\RepoServiceInterface;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Pagination\LengthAwarePaginator;
use Illuminate\Support\Facades\Redis;
use Jenssegers\Mongodb\Query\Builder;

class WxClientRepo implements RepoServiceInterface
{
    const FREEZE_KEY = 'locks-wx-ids';

    /**
     * @param array|null $_options
     * @return Model
     * <code>
     *  $repo->create(['name' => '']);
     * </code>
     */
    public function create(array $_options = null):Model
    {
        $wxClient = new WxClient();
        $wxClient->mobile = $_options['mobile'];
        $wxClient->password = $_options['password'];
        $wxClient->nickName = $_options['nickName'];
        $wxClient->uin = 0;
        $wxClient->status = $_options['status'];
        $wxClient->qrcode = $_options['qrcode'];
        $wxClient->project_id = '';
        $wxClient->loginMobile = array_get($_options, 'loginMobile', '');
        $wxClient->contacts = [];
        $wxClient->save();
        return $wxClient;
    }

    public function read($limit = 0)
    {
        $inputs = Helper::get_filter();
        $wxClients = WxClient::search($inputs)->orderBy('created_at', 'desc')->paginate(20);
        $items = $wxClients->map(function ($wxClient) {
            return $this->wxClientInfo($wxClient, $wxClient::WXCLIENT_LIST_FIELDS);
        });
        $wxClients = new LengthAwarePaginator($items,
            $wxClients->total(), 20, request()->input('page', 1));
        return $wxClients;
    }

    public function find(array $_filter):Model
    {
        $res = WxClient::find($_filter)->first();
        if (!is_null($res)) {
            return $res;
        } else {
            return new WxClient();
        }
    }

    public function update(array $_filter, array $_update_data):bool
    {
        $wxClient = WxClient::find($_filter)->first();
        if (!is_null($wxClient)) {
            return $wxClient->update($_update_data);
        } else {
            return false;
        }
    }

    public function delete(array $_filter):bool
    {
        // TODO: Implement delete() method.
    }

    /**
     * 锁定空闲微信号, 暂时不可再分配
     * @param array $_ids
     * @return bool
     */
    public function freeze(array $_ids):bool
    {
        Redis::sadd(self::FREEZE_KEY, $_ids);
        Redis::expire(self::FREEZE_KEY, 120);
        //将锁定微信号添加至session
        $wx_ids = request()->session()->get('wx_ids', []);
        $wx_ids = array_merge($wx_ids, $_ids);
        request()->session()->put('wx_ids', $wx_ids);
        return true;
    }

    /**
     * 手动解锁空闲微信号
     * @return bool
     */
    public function unfreeze()
    {
        if (Redis::exists(self::FREEZE_KEY)) {
            $wx_ids = request()->session()->get('wx_ids', []);
            request()->session()->forget('wx_ids');
            return Redis::srem(self::FREEZE_KEY, $wx_ids);
        }
        return true;
    }

    /**
     * 获取当前锁定的微信号号IDs
     */
    public function getFreezeIds()
    {
        return Redis::smembers(self::FREEZE_KEY) ?? [];
    }

    /**
     * 获取指定空闲的微信号
     * @param int $count
     * @return array|Collection|static[]
     */
    public function getFreeClients(int $count = 0)
    {
        $filter = [
            'status' => 1,
            Helper::makeMongoEmptyFilter('company_id'),
        ];
        $freezes = $this->getFreezeIds();
        $query = WxClient::where($filter);
        if (count($freezes) > 0) {
            $query = $query->whereNotIn('_id', $freezes);
        }
        /** @var Builder $query */
        $clients = $count > 0 ? $query->limit($count)->get() : $query->get();
        return $clients;
    }

    /**
     *
     * @param $company_id
     * @param $clientIds
     */
    public function setClientsToCompany($company_id, array $clientIds)
    {
        if (empty($company_id)) return [];
        $isExists = Company::withTrashed()->find($company_id)->exists();
        if (!$isExists) return [];

        $realAddIds = WxClient::whereIn('_id', $clientIds)
            ->where([Helper::makeMongoEmptyFilter('company_id')]) // 查找project_id为空的微信号
            ->pluck('_id')->all();

        $wr = WxClient::whereIn('_id', $realAddIds)->update(['company_id' => $company_id]);
        $sr = SimCard::whereIn('wxClient_id', $realAddIds)->update(['company_id' => $company_id]);

        if (config('app.config')) {
            logger('【DEBUG】--- update wxClient IDs: ' . json_encode($clientIds));
        }
        return $realAddIds;
    }

    public function unsetClientsFromCompany($company_id, array $clientIds) {
        if (empty($company_id)) return false;
        $isExists = Company::withTrashed()->find($company_id)->exists();
        if (!$isExists) return false;

        // 检查要删除的微信号有没有好友,有的就不删除
        $realDelIds = WxClient::whereIn('_id', $clientIds)
            ->where(['contacts' => array('$size' => 0)])// 查找没有联系人的微信号
            ->where([Helper::makeMongoEmptyFilter('project_id')])// 查找project_id为空的微信号
            ->pluck('_id')->all();
        if (!empty($realDelIds)) {
            WxClient::whereIn('_id', $realDelIds)->update(['company_id' => null, 'project_id' => null]);
            SimCard::whereIn('wxClient_id', $realDelIds)->update(['company_id' => null]);
            return true;
        }
        return false;
    }

    //根据传入字段返回参数
    public function wxClientInfo(WxClient $wx_client, array $fields): Model
    {
        $result = new WxClient();
        $fields = array_merge($fields, ['id', '_id']);
        foreach ($fields as $field) {
            $function_name = 'get' . ucfirst($field);
            $result->$field = $wx_client->$field
                ?? (method_exists($this, $function_name)
                    ? $this->$function_name($wx_client) : null);
        }
        return $result;
    }

    //登录状态
    public function getLoginStatus(WxClient $wx_client):int
    {
        if (!is_null($wx_client->loginStatus)) {
            return $wx_client->loginStatus;
        }
        return $wx_client->uin
            ? (int)Client::isActive($wx_client->uin) : 0;
    }

    //卡位柜
    public function getIndex(WxClient $wx_client):array
    {
        return ($wx_client->simCard instanceof SimCard)
            ? $wx_client->simCard->index : [];
    }

    //所属渠道
    public function getCompanyName(WxClient $wx_client)
    {
        return ($wx_client->company instanceof Company)
            ? $wx_client->company->name : null;
    }

    //所属结构
    public function getProjectName(WxClient $wx_client)
    {
        return ($wx_client->project instanceof Project)
            ? $wx_client->project->title : null;
    }

    //操作
    public function getOperation(WxClient $wx_client):array
    {
        $status = [1, 2];
        $loginStatus = [0, 1, -1];
        $result = [];
        if (is_null($wx_client->loginStatus)) {
            $wx_client->loginStatus = $this->getLoginStatus($wx_client);
        }
        if (in_array($wx_client->status, $status)
            && in_array($wx_client->loginStatus, $loginStatus)
        ) {
            $operation
                = config('wxoperation.operation.'
                . $wx_client->loginStatus . '-' . $wx_client->status);
            if (is_array($operation)) {
                foreach ($operation as $value) {
                    $temp['key'] = $value;
                    $temp['url'] = config('wxoperation.url.' . $value);
                    array_push($result, $temp);
                }
            }
        }
        return $result;
    }

    /**
     * 批量导入微信号
     */

    public function importWx($filePath,$fileName)
    {
        //获取表格内数据
        $allExcelInfo = HelpService::getExcelInfo($filePath);
        $excel_content = $allExcelInfo['excelContent'];
        $firstKey = $allExcelInfo['firstKey'];
        if (!in_array('卡位', $firstKey)
            || !in_array('微信昵称', $firstKey)
            || !in_array('微信密码', $firstKey)
            || !in_array('账号状态', $firstKey)
            || !in_array('加好友二维码内容', $firstKey)
            || !in_array('登陆手机', $firstKey)
        ) {
            return ['列名缺失'];
        }
        //导入错误信息类
        $error = new ImportError();
        foreach ($excel_content as $row) {
            $card_index = (int)$row['卡位'];
            //数据有效性验证
            $status = $row['账号状态'];
            if (!in_array($status, ['被封', '正常']) && !$card_index) {
                continue;
            }
            if (!in_array($status, ['被封', '正常']) || !$card_index) {
                $error->addErrorIndex($error::MISSING_INFO,
                    $row['index']);
                continue;
            }

            if (empty($row['卡位'])) {
                $error->addErrorIndex($error::NOT_HAS_KW,
                    $row['index']);
                continue;
            }

            if (empty($row['微信昵称'])) {
                $error->addErrorIndex($error::NOT_HAS_NAME,
                    $row['index']);
                continue;
            }

            if (empty($row['微信密码'])) {
                $error->addErrorIndex($error::NOT_HAS_PWD,
                    $row['index']);
                continue;
            }

            if (empty($row['账号状态'])) {
                $error->addErrorIndex($error::NOT_HAS_STATUS,
                    $row['index']);
                continue;
            }

            if (empty($row['加好友二维码内容'])) {
                $error->addErrorIndex($error::NOT_HAS_EWMCONTENT,
                    $row['index']);
                continue;
            }

            $simCard = SimCard::where([
                '$or' => [
                    ['indexCache' => $card_index]
                ]
            ])->get();
            //数据是否可写入验证
            switch ($simCard->count()) {
                case 0:
                    $error->addErrorIndex($error::SIMCARD_NOT_EXIST,
                        $row['index']);
                    break;
                case 1:
                    if ($simCard->get(0)->wxClient_id) {
                        $error->addErrorIndex($error::SIMCARD_HAS_WX,
                            $row['index']);
                    }
                    if (empty($simCard->get(0)->mobile)) {
                        $error->addErrorIndex($error::NOT_HAS_MOBILE,
                            $row['index']);
                    }
                    if ($wx_client = WxClient::where('mobile', $simCard->get(0)->mobile)->count()) {
                        $error->addErrorIndex($error::MOBILE_HAS_WX,
                            $row['index']);
                    }
                    if (!empty($simCard->get(0)->mobile)
                        && !(WxClient::where('mobile', $simCard->get(0)->mobile)->count())
                        && empty($simCard->get(0)->wxClient_id)
                    ) {
                        $wxStatus = $row['账号状态'] == '被封' ? 2 : 1;
                        $data = [
                            'mobile' => $simCard->get(0)->mobile,
                            'qrcode' => $row['加好友二维码内容'],
                            'nickName' => $row['微信昵称'],
                            'password' => $row['微信密码'],
                            'status' => $wxStatus,
                        ];
                        $wx_info = $this->create($data);

                        if ($wx_info) {
                            DB::table('sim_cards')
                                ->where([
                                    '_id' => $simCard->get(0)->_id,
                                ])->update(['wxClient_id' => $wx_info->_id]);
                        }
                    }
                    break;
                default:
                    $error->addErrorIndex($error::NOT_KNOW_ERROR,
                        $row['index']);
            }
        }
        //错误信息格式化
        if (!file_exists(storage_path('logs/wxLog'))){
            Helper::makeDir(storage_path('logs/wxImportLog'));
        }
        file_put_contents(storage_path('logs/wxImportLog/wx.log'),'文件'.$fileName.'错误信息'.':'.implode(' ',$error->getMessage()).PHP_EOL,FILE_APPEND);
        return $error->getMessage();
    }

}
